#include "ob_table_id_name.h"
#include "utility.h"

using namespace oceanbase;
using namespace common;
using namespace nb_accessor;

ObTableIdNameIterator::ObTableIdNameIterator()
   :need_scan_(false), only_core_tables_(true), index(false),
   table_idx_(-1), client_proxy_(NULL), res_(NULL),res2_(NULL)
    //add jinty 20160121:b
    ,op_res_(NULL)
    //add e
{
}

ObTableIdNameIterator::~ObTableIdNameIterator()
{
  this->destroy();
  need_scan_ = true;
}

bool ObTableIdNameIterator::check_inner_stat()
{
  bool ret = true;
  if (NULL == client_proxy_)
  {
    ret = false;
    TBSYS_LOG(ERROR, "not init");
  }
  else
  {
    if (need_scan_)
    {
      ObNewRange range;
      range.border_flag_.unset_inclusive_start();
      range.border_flag_.set_inclusive_end();
      range.set_whole_range();
      int err = OB_SUCCESS;
      if(OB_SUCCESS != (err = nb_accessor_.scan(res_, FIRST_TABLET_TABLE_NAME, range, SC("table_name")("table_id"))))
      {
        TBSYS_LOG(WARN, "nb accessor scan fail:ret[%d]", err);
        ret = false;
      }
      //add longfei [craete index]
      if(OB_SUCCESS != (err = nb_accessor_.scan(res2_, OB_ALL_SECONDAYR_INDEX_TABLE_NAME, range, SC("table_name")("table_id"))))
      {
        TBSYS_LOG(WARN, "nb accessor scan fail in secondary index:ret[%d]", err);
        ret = false;
      }
      //add e
      else
      {
        TBSYS_LOG(DEBUG, "scan first_tablet_table success. scanner row count =%ld", res_->get_scanner()->get_row_num());
        TBSYS_LOG(DEBUG, "scan all_secondary_index success. scanner row count =%ld", res2_->get_scanner()->get_row_num());
        need_scan_ = false;
      }
    }
    //need add core_schema to res_
  }
  return ret;
}
//add jinty 20160119:b
bool ObTableIdNameIterator::check_inner_stat2()
{
  bool ret = true;
  if (NULL == client_proxy_)
  {
    ret = false;
    TBSYS_LOG(ERROR, "not init");
  }
  else
  {
    if (need_scan_)
    {
      ObNewRange range;
      int err = OB_SUCCESS;

      if (cur_version_ > 0)
      {
        range.border_flag_.unset_inclusive_start();
        range.border_flag_.set_inclusive_end();

        ObObj start_version;
        start_version.set_int(pre_version_);
        range.start_key_.assign(&start_version,1);

        ObObj end_version;
        end_version.set_int(cur_version_);
        range.end_key_.assign(&end_version,1);
        //add jinty debug 20160121
         TBSYS_LOG(ERROR, "debug::jinty>>>start_version[%ld],end_version[%ld]",pre_version_, cur_version_);
         TBSYS_LOG(ERROR, "debug:jinty>>>here is ObTableIdNameIterator::check_inner_stat_for_OpTable");
        //add e
        if(OB_SUCCESS != (err = nb_accessor_.scan(op_res_, OB_ALL_TABLE_OPERATION_NAME, range, SC("table_id")("operation_type"))))
        {
          TBSYS_LOG(WARN, "nb accessor scan fail:ret[%d]", err);
          ret = false;
        }
        else
        {
          //add jty debug 20160121
          TBSYS_LOG(ERROR, "debug::jinty>>>scan table_operation success. scanner row count =%ld", op_res_->get_scanner()->get_row_num());
          //add e
          TBSYS_LOG(DEBUG,"scan table_operation success. scanner row count =%ld", op_res_->get_scanner()->get_row_num());
         // need_scan_ = false;
        }
      }

      if (err != OB_SUCCESS)
      {
        TBSYS_LOG(WARN, "nb accessor scan fail:ret[%d]", err);
        ret = false;
      }
      else
      {
        range.set_whole_range();//all range
        if(OB_SUCCESS != (err = nb_accessor_.scan(res_, FIRST_TABLET_TABLE_NAME, range, SC("table_name")("table_id"))))
        {
          TBSYS_LOG(WARN, "nb accessor scan fail:ret[%d]", err);
          ret = false;
        }
        if(OB_SUCCESS != (err = nb_accessor_.scan(res2_, OB_ALL_SECONDAYR_INDEX_TABLE_NAME, range, SC("table_name")("table_id"))))
        {
          TBSYS_LOG(WARN, "nb accessor scan fail in secondary index:ret[%d]", err);
          ret = false;
        }
        else
        {
          TBSYS_LOG(DEBUG, "scan first_tablet_table success. scanner row count =%ld", res_->get_scanner()->get_row_num());
          TBSYS_LOG(DEBUG, "scan all_secondary_index success. scanner row count =%ld", res2_->get_scanner()->get_row_num());
          need_scan_ = false;
        }
      }
    }//end if(need_scan_)
  }
  return ret;
}
//add e

int ObTableIdNameIterator::init(ObScanHelper* client_proxy, bool only_core_tables)
{
  int ret = OB_SUCCESS;
  if(NULL == client_proxy)
  {
    ret = OB_INVALID_ARGUMENT;
    TBSYS_LOG(WARN, "client_proxy is null");
  }

  if(OB_SUCCESS == ret)
  {
    this->only_core_tables_ = only_core_tables;
    this->client_proxy_ = client_proxy;
    table_idx_ = -1;
    if (only_core_tables == false)
    {
      need_scan_ = true;
      ret = nb_accessor_.init(client_proxy);
      if(OB_SUCCESS != ret)
      {
        TBSYS_LOG(WARN, "init nb_accessor fail:ret[%d]", ret);
      }
      else
      {
        nb_accessor_.set_is_read_consistency(true);
      }
    }
  }
  return ret;
}
//add jinty 20160119:b
int ObTableIdNameIterator::initForOpTable(ObScanHelper *client_proxy, bool only_core_tables, int64_t pre_version, int64_t cur_version)
{
  int ret=OB_SUCCESS;
  if(NULL == client_proxy)
  {
    ret = OB_INVALID_ARGUMENT;
    TBSYS_LOG(WARN, "client_proxy is null");
  }

  if(OB_SUCCESS == ret)
  {
    this->only_core_tables_ = only_core_tables;
    this->client_proxy_ = client_proxy;
    table_idx_ = -1;
    pre_version_ = pre_version;
    cur_version_ = cur_version;
    if (only_core_tables == false)
    {
      need_scan_ = true;
      ret = nb_accessor_.init(client_proxy);
      if(OB_SUCCESS != ret)
      {
        TBSYS_LOG(WARN, "init nb_accessor fail:ret[%d]", ret);
      }
      else
      {
        nb_accessor_.set_is_read_consistency(true);
      }
    }
  }
  return ret;
}
int ObTableIdNameIterator::get_table_array(ObArray<int64_t> &create_table_id, ObArray<int64_t> &drop_table_id, bool &need_refresh)
{
  int ret = OB_SUCCESS;
  if(!check_inner_stat2())            //1 set query range accord pre_version and cur_version
  {                                  //2 set table_name for query (here is _all_first_table_entry ,_all_table_opration, _all_secondary_index)
                                     //3 store into res_ ,res1_ and op_res_
     ret = OB_ERROR;
     TBSYS_LOG(WARN,"check inner status fail");
  }
  need_refresh = false;
  //start query _all_table_opration
  while(OB_SUCCESS == ret)
  {
    TableRow* table_row = NULL;
    int64_t op_type = 0;
    if (NULL == op_res_)
    {
      ret = OB_ERR_UNEXPECTED;
      TBSYS_LOG(ERROR,"op_res_ is NULL");
    }
    else
    {
      ret = op_res_->next_row();
    }

    if (OB_SUCCESS != ret && OB_ITER_END != ret)
    {
      TBSYS_LOG(WARN, "ObTableIdNameIterator::get_table_array--next row fail:ret[%d]", ret);
    }
    if(OB_SUCCESS == ret)
    {
      if(OB_SUCCESS != (ret = op_res_->get_row(&table_row)))
      {
        TBSYS_LOG(WARN, "ObTableIdNameIterator::get_table_array--get row fail:ret[%d]", ret);
      }
    }

    ObCellInfo* cell_info = NULL;
    if(OB_SUCCESS == ret)
    {
      cell_info = table_row->get_cell_info("operation_type");
      if(NULL != cell_info)
      {
        if (OB_SUCCESS != (ret = cell_info->value_.get_int(op_type)))
        {
          TBSYS_LOG(ERROR, "ObTableIdNameIterator::get_table_array--get operation_type fail, ret = %d",ret);
        }
        else if (REFRESH_SCHEMA == op_type)
        {
          need_refresh = true;
          TBSYS_LOG(INFO, "refresh schema");
          break;// do not need to get table id
        }
      }
      else
      {
        ret = OB_ERROR;
        TBSYS_LOG(WARN, "get operation_type cell info fail");
      }
    }//end of geting table_name

    if(OB_SUCCESS == ret && !need_refresh)
    {
      cell_info = table_row->get_cell_info("table_id");
      if(NULL != cell_info)
      {
        int64_t table_id = 0;
        ret = cell_info->value_.get_int(table_id);
        if (OB_SUCCESS != ret)
        {
          TBSYS_LOG(ERROR, "get table_id fail, ret = %d",ret);
        }
        else
        {
          TBSYS_LOG(ERROR,"Test::Jinty>>>op_type[%ld]",op_type);
          switch(op_type)
          {
          case CREATE_TABLE:
            if (OB_SUCCESS != (ret = create_table_id.push_back(table_id)))
            {
              TBSYS_LOG(ERROR, "memory overflow");
            }
            break;
          case DROP_TABLE:
            if (OB_SUCCESS != (ret = drop_table_id.push_back(table_id)))
            {
              TBSYS_LOG(ERROR, "memory overflow");
            }
            break;
          case ALTER_TABLE:
            if (OB_SUCCESS != (ret = drop_table_id.push_back(table_id)))
            {
              TBSYS_LOG(ERROR, "memory overflow");
            }
            else if (OB_SUCCESS != (ret = create_table_id.push_back(table_id)))
            {
              TBSYS_LOG(ERROR, "memory overflow");
            }
            break;
          default:
            ret = OB_ERROR;
            TBSYS_LOG(ERROR, "unknow type:%ld",op_type);
            break;
          }
        }
      }//cell_info = NULL
      else
      {
        ret = OB_ERROR;
        TBSYS_LOG(WARN, "get table_id cell info fail");
      }
    }//end of geting table_id
  }//end while
  //never can happen
  if (OB_ITER_END == ret)
  {
    ret = OB_SUCCESS;
  }
  return ret;
}
//add e
int ObTableIdNameIterator::next()
{
  int ret = OB_SUCCESS;
  if(!check_inner_stat())//set range for query _first_table_entry and _all_secondary_index
  {
    ret = OB_ERROR;
    TBSYS_LOG(WARN, "check inner stat fail");
  }
  if(OB_SUCCESS == ret)
  {
    if (only_core_tables_ == true)
    {
      ++table_idx_;
      TBSYS_LOG(DEBUG, "table_idx=%d", table_idx_);
      if (table_idx_ < CORE_TABLE_COUNT) //longfei [create index]
      {
        // we have three basic tables: __first_tablet_entry, __all_all_column, __all_all_join
      }
      else
      {
        ret = OB_ITER_END;
      }
    }
    else
    {
      ++table_idx_;
      TBSYS_LOG(DEBUG, "table_idx=%d", table_idx_);
      if (table_idx_ < CORE_TABLE_COUNT) //longfei [create index]
      {
        // we have three basic tables: __first_tablet_entry, __all_all_column, __all_all_join
      }
      else if (NULL == res_)
      {
        TBSYS_LOG(ERROR, "results is NULL");
        ret = OB_ERR_UNEXPECTED;
      }
      else
      {
        ret = res_->next_row();
        if(OB_SUCCESS != ret && OB_ITER_END != ret)
        {
          TBSYS_LOG(WARN, "next row fail:ret[%d]", ret);
        }
        // add longfei [create index]
        //TBSYS_LOG(ERROR,"LONGFEI:the return value of res_->next_row() is %d",ret);

        if(OB_ITER_END == ret)
        {
          ret = res2_->next_row();
          index = true;
        }
        if(OB_SUCCESS != ret && OB_ITER_END != ret)
        {
          TBSYS_LOG(WARN, "next row fail:ret[%d]", ret);
        }

        // add e
      }
    }
  }
  return ret;
}

int ObTableIdNameIterator::get(ObTableIdName** table_info)
{
  int ret = OB_SUCCESS;
  if (0 > table_idx_)
  {
    ret = OB_ERR_UNEXPECTED;
    TBSYS_LOG(ERROR, "get failed");
  }
  else if (table_idx_ < CORE_TABLE_COUNT)
  {
    ret = internal_get(table_info);
  }
  else
  {
    if (only_core_tables_ == true)
    {
      ret = OB_INNER_STAT_ERROR;
      TBSYS_LOG(WARN, "get core tables but table_idx[%d]_ >= 3", table_idx_);
    }
    else
    {
      ret = normal_get(table_info, index);
    }
  }
  if (OB_SUCCESS == ret)
  {
    TBSYS_LOG(DEBUG, "table_name: [%.*s], table_id: [%ld]",
        (*table_info)->table_name_.length(),
        (*table_info)->table_name_.ptr(), (*table_info)->table_id_);
  }
  return ret;
}

int ObTableIdNameIterator::internal_get(ObTableIdName** table_info)
{
  int ret = OB_SUCCESS;
  switch(table_idx_)
  {
    case 0:
      table_id_name_.table_name_.assign_ptr(const_cast<char*>(FIRST_TABLET_TABLE_NAME),
          static_cast<int32_t>(strlen(FIRST_TABLET_TABLE_NAME)));
      table_id_name_.table_id_ = OB_FIRST_TABLET_ENTRY_TID;
      *table_info = &table_id_name_;
      break;
    case 1:
      table_id_name_.table_name_.assign_ptr(const_cast<char*>(OB_ALL_COLUMN_TABLE_NAME),
          static_cast<int32_t>(strlen(OB_ALL_COLUMN_TABLE_NAME)));
      table_id_name_.table_id_ = OB_ALL_ALL_COLUMN_TID;
      *table_info = &table_id_name_;
      break;
    case 2:
      table_id_name_.table_name_.assign_ptr(const_cast<char*>(OB_ALL_JOININFO_TABLE_NAME),
          static_cast<int32_t>(strlen(OB_ALL_JOININFO_TABLE_NAME)));
      table_id_name_.table_id_ = OB_ALL_JOIN_INFO_TID;
      *table_info = &table_id_name_;
      break;
    case 3: //longfei [create index]
      table_id_name_.table_name_.assign_ptr(const_cast<char*>(OB_ALL_SECONDAYR_INDEX_TABLE_NAME),
          static_cast<int32_t>(strlen(OB_ALL_SECONDAYR_INDEX_TABLE_NAME)));
      table_id_name_.table_id_ = OB_ALL_SECONDARY_INDEX_TID;
      *table_info = &table_id_name_;
      break;
    //add jinty 20160119:b
    case 4:
      table_id_name_.table_name_.assign_ptr(const_cast<char*>(OB_ALL_TABLE_OPERATION_NAME),
        static_cast<int32_t>(strlen(OB_ALL_TABLE_OPERATION_NAME)));
      table_id_name_.table_id_ = OB_ALL_TABLE_OPERATION_TID;
      *table_info = &table_id_name_;
      break;
    //add e
    default:
      ret = OB_ERR_UNEXPECTED;
      TBSYS_LOG(ERROR, "unexpected branch");
      break;
  }
  return ret;
}

int ObTableIdNameIterator::normal_get(ObTableIdName** table_id_name,bool index)
{
  int ret = OB_SUCCESS;

  TableRow* table_row = NULL;
  if (NULL == res_)
  {
    ret = OB_ERR_UNEXPECTED;
    TBSYS_LOG(ERROR, "results is NULL");
  }

  if(OB_SUCCESS == ret && !index)
  {
    ret = res_->get_row(&table_row);
    //TBSYS_LOG(ERROR,"LONGFEI:the ret of get row is %d",ret);
    if(OB_SUCCESS != ret && OB_ITER_END != ret)
    {
      TBSYS_LOG(WARN, "get row fail:ret[%d]", ret);
    }
  }
  //add longfei [create index]
  if(OB_SUCCESS == ret && index)
  {
    ret = res2_->get_row(&table_row);
    //TBSYS_LOG(ERROR,"LONGFEI:the ret of get row is %d",ret);
    if(OB_SUCCESS != ret && OB_ITER_END != ret)
    {
      TBSYS_LOG(WARN, "get row fail:ret[%d]", ret);
    }
  }
  //add e

  ObCellInfo* cell_info = NULL;
  if(OB_SUCCESS == ret)
  {
    cell_info = table_row->get_cell_info("table_name");
    if(NULL != cell_info)
    {
      if (cell_info->value_.get_type() == ObNullType
          && cell_info->row_key_.get_obj_cnt() > 0
          && cell_info->row_key_.get_obj_ptr()[0].get_type() == ObVarcharType)
      {
        TBSYS_LOG(WARN, "value is null,  get table name from cell rowkey:%s", print_cellinfo(cell_info));
        cell_info->row_key_.get_obj_ptr()[0].get_varchar(table_id_name_.table_name_);
      }
      else
      {
        cell_info->value_.get_varchar(table_id_name_.table_name_);
      }
    }
    else
    {
      ret = OB_ERROR;
      TBSYS_LOG(WARN, "get table_name cell info fail");
    }
  }

  if(OB_SUCCESS == ret)
  {
    cell_info = table_row->get_cell_info("table_id");
    if(NULL != cell_info)
    {
      int64_t tmp = 0;
      cell_info->value_.get_int(tmp);
      table_id_name_.table_id_ = static_cast<uint64_t>(tmp);
      if (tmp == 0)
      {
        TBSYS_LOG(INFO, "get table_id = 0");
      }
    }
    else
    {
      ret = OB_ERROR;
      TBSYS_LOG(WARN, "get table_id cell info fail");
    }
  }

  if(OB_SUCCESS == ret)
  {
    *table_id_name = &table_id_name_;
  }
  return ret;
}

void ObTableIdNameIterator::destroy()
{
  if(NULL != res_)
  {
    nb_accessor_.release_query_res(res_);
    res_ = NULL;
  }
  // add longfei [create index]
  if(NULL != res2_)
  {
    nb_accessor_.release_query_res(res2_);
    res2_ = NULL;
  }
  // add e
}

